﻿Imports FairShop.Operaties

''' <summary>
''' Formulier om de inventaris op te maken
''' </summary>
Public Class InventarisForm

    Private _mainForm As Form

#Region "Public property's"

    Private _kanBewaren As Boolean
    Public Property KanBewaren() As Boolean
        Get
            Return _kanBewaren
        End Get
        Set(ByVal value As Boolean)
            _kanBewaren = value
            tsbBewaren.Enabled = value
        End Set
    End Property

#End Region

#Region "Constructor"

    Public Sub New(ByVal mainForm As Form)
        Me.InitializeComponent()
        _mainForm = mainForm
    End Sub

    Protected Overrides Sub OnLoad(ByVal e As EventArgs)
        MyBase.OnLoad(e)
        Try
            Cursor = Cursors.WaitCursor

            Me.CategorieenBindingSource.DataSource = Utility.Data
            Me.LeveranciersBindingSource.DataSource = Utility.Data
            Me.ArtikelsDataSetBindingSource.DataSource = Utility.Data
            Me.ArtikelsDataSetBindingSource.Filter = "Voorraad <> 0"

            InitGrid()
            KanBewaren = False
        Catch ex As Exception
            MsgBox.ShowError("Fout tijdens het inladen van de gegevens")
            log.WriteError("InventarisForm_Load", ex)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

#End Region

#Region "Event handling"

    Private Sub tsbAfsluiten_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbAfsluiten.Click
        Me.Close()
    End Sub

    Protected Overrides Sub OnKeyUp(ByVal e As System.Windows.Forms.KeyEventArgs)
        MyBase.OnKeyUp(e)
        Select Case e.KeyCode
            Case Keys.F12
                Me.Close()
            Case Keys.F2
                If (Not KanBewaren) Then Return
                BewaarWijzigingen()
            Case Keys.F3
                If (Not tsbVerwijderen.Enabled) Then Return
                Verwijderen()
            Case Keys.F5
                If (Not tsbWijzigen.Enabled) Then Return
                If (Grid1.SelectedRows.Count > 0) Then
                    BeheerArtikel(Grid1.SelectedRows(0).Index)
                End If
        End Select
    End Sub

    Private Sub InvoerArtikelsControl1_BarcodeConfirmed(ByVal sender As System.Object, ByVal e As InvoerArtikelsControl.BarcodeConfirmedEventArgs) _
            Handles InvoerArtikelsControl1.BarcodeConfirmed
        Try
            Dim eersteArtikelMetDezeBarcode As ArtikelsDataSet.ArtikelsRow = ArtikelsBL.GetEersteVerkoopbaarArtikelMetBarcode(InvoerArtikelsControl1.Barcode)

            If (eersteArtikelMetDezeBarcode Is Nothing) Then
                ' barcode niet gevonden in dataset
                e.BarcodeStatus = VoegArtikelMetNieuweBarcodeToe(InvoerArtikelsControl1.Aantal)
            Else
                ' barcode gevonden in de dataset
                Dim artikels As List(Of ArtikelSamenstelling.Artikel) = Utility.ArtikelSamenstelling.GetArtikels(eersteArtikelMetDezeBarcode)
                Dim ingevoerdAantal As Integer = InvoerArtikelsControl1.Aantal
                For Each artikel As ArtikelSamenstelling.Artikel In artikels
                    Dim aantal As Integer = ingevoerdAantal * artikel.Aantal
                    If (artikel.ArtikelRij.Voorraad <> 0) Then
                        ' barcode staat al in de grid, toon barcode in speciale kleur om op te vallen
                        ArtikelsDataSetBindingSource.Position = ArtikelsDataSetBindingSource.Find("ID", artikel.ArtikelRij.Id)

                        artikel.ArtikelRij.Voorraad += aantal
                        Me.InvoerArtikelsControl1.Clear()
                        Me.lblVerwachteVoorraad.Text = artikel.ArtikelRij.VerwachteVoorraad.ToString()
                        Me.lblReedsGeteldAantal.Text = artikel.ArtikelRij.Voorraad.ToString()
                        KanBewaren = True

                        Sound.PlayWarning() ' verwittig de gebruiker dat de barcode al in de lijst staat
                        ' toon de barcode in een speciale kleur om op te vallen
                        e.BarcodeStatus = InvoerArtikelsControl.BarcodeStatusType.Speciaal
                    Else
                        ' barcode staat nog niet in de grid
                        e.BarcodeStatus = VoegArtikelMetBestaandeBarcodeToe(artikel.ArtikelRij, aantal)
                    End If
                Next
            End If
        Catch ex As Exception
            MsgBox.ShowError("Fout tijdens het inladen van de gegevens")
            log.WriteError("InventarisForm.InvoerArtikelsControl1_BarcodeConfirmed", ex)
            e.BarcodeStatus = InvoerArtikelsControl.BarcodeStatusType.Invalid
        End Try
    End Sub

    Private Sub tsbBewaren_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbBewaren.Click
        BewaarWijzigingen()
    End Sub

    Private Sub Grid1_SelectionChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Grid1.SelectionChanged
        If (Grid1.SelectedRows.Count = 0) Then
            lblVerwachteVoorraad.Text = ""
            lblReedsGeteldAantal.Text = ""
            Me.tsbVerwijderen.Enabled = False
            Me.tsbWijzigen.Enabled = False
            Return
        Else
            Dim row As DataGridViewRow = Grid1.SelectedRows(0)
            Try
                Me.tsbVerwijderen.Enabled = True
                Me.tsbWijzigen.Enabled = True
                lblVerwachteVoorraad.Text = DataGridViewHelper.GetValueFromDataGridRow(Utility.Data.Artikels.VerwachteVoorraadColumn.ColumnName, row).ToString()
                lblReedsGeteldAantal.Text = DataGridViewHelper.GetValueFromDataGridRow(Utility.Data.Artikels.VoorraadColumn.ColumnName, row).ToString()
            Catch ex As Exception
                ' soms schijnt de rij geen "Voorraad"-item te hebben en dan kom je hier
                row.ErrorText = ex.Message
                log.WriteError("InventarisForm.Grid1_SelectionChanged", ex)
            End Try
        End If
    End Sub

    Protected Overrides Sub OnFormClosing(ByVal e As FormClosingEventArgs)
        MyBase.OnFormClosing(e)
        If (Utility.HasChanges(Utility.Data.Artikels)) Then
            Dim result As DialogResult = MessageBox.Show("De voorraad is veranderd. Wil je de wijzigingen bewaren?", "Bewaren", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation)
            Select Case result
                Case Windows.Forms.DialogResult.Yes
                    BewaarWijzigingen()
                Case Windows.Forms.DialogResult.Cancel
                    e.Cancel = True
                    Return
                Case Windows.Forms.DialogResult.No
                    ' annuleer de wijzigingen en laat sluiten
                    Utility.Data.Artikels.RejectChanges()
            End Select
        End If
        ' We have to dispose of the grid before the form closes to avoid possible DataErrors from the GridViewComboBoxColumn
        Me.Grid1.Dispose()
        _mainForm.BringToFront()
    End Sub

    Private Sub Grid1_DataError(ByVal sender As Object, ByVal e As DataGridViewDataErrorEventArgs) Handles Grid1.DataError
        MsgBox.ShowError("Ongeldige invoer. Bij een wijziging, druk Esc om de vorige waarde te herstellen")
        log.WriteError("InventarisForm.Grid1_DataError", e.Exception)
        e.Cancel = True
    End Sub

    Private Sub Grid1_CellDoubleClick(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles Grid1.CellDoubleClick
        BeheerArtikel(e.RowIndex)
    End Sub

    Private Sub tsbVerwijderen_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles tsbVerwijderen.Click
        Verwijderen()
    End Sub

    Private Sub BindingNavigatorDeleteItem_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BindingNavigatorDeleteItem.Click
        Verwijderen()
    End Sub

    Private Sub tsbWijzigen_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles tsbWijzigen.Click
        If (Grid1.SelectedRows.Count = 1) Then
            BeheerArtikel(Grid1.SelectedRows(0).Index)
        End If
    End Sub

#End Region

#Region "Helperfuncties"

    Private Sub InitGrid()
        With DataGridViewHelper.GetGridColumnByDataName(Utility.Data.Artikels.IdColumn.ColumnName, Grid1)
            .Visible = False ' Autonumber niet tonen
        End With
        With DataGridViewHelper.GetGridColumnByDataName(Utility.Data.Artikels.OmschrijvingColumn.ColumnName, Grid1)
            .Width = 240
        End With
        With DataGridViewHelper.GetGridColumnByDataName(Utility.Data.Artikels.BarcodeColumn.ColumnName, Grid1)
            .Width = 100
        End With
        With DataGridViewHelper.GetGridColumnByDataName(Utility.Data.Artikels.VoorraadColumn.ColumnName, Grid1)
            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        End With
        With DataGridViewHelper.GetGridColumnByDataName(Utility.Data.Artikels.VerwachteVoorraadColumn.ColumnName, Grid1)
            .HeaderText = "Verwacht"
            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        End With
        With DataGridViewHelper.GetGridColumnByDataName(Utility.Data.Artikels.PrijsColumn.ColumnName, Grid1)
            .Width = 80
            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
            .DefaultCellStyle.Format = "c"
        End With
        With DataGridViewHelper.GetGridColumnByDataName(Utility.Data.Artikels.IdLeverancierColumn.ColumnName, Grid1)
            .HeaderText = "Leverancier"
        End With
        With DataGridViewHelper.GetGridColumnByDataName(Utility.Data.Artikels.IdCategorieColumn.ColumnName, Grid1)
            .HeaderText = "Categorie"
        End With
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="aantal"></param>
    ''' <returns></returns>
    Private Function VoegArtikelMetNieuweBarcodeToe(ByVal aantal As Integer) As InvoerArtikelsControl.BarcodeStatusType
        Sound.PlayError() ' nieuw artikel is niet echt een error, maar verwittig de gebruiker dat de barcode niet gevonden is

        ' laat nieuw artikel toevoegen door gebruiker
        Dim insertForm As New BeheerArtikelForm(Me.InvoerArtikelsControl1.Barcode, aantal)
        If (insertForm.ShowDialog = DialogResult.OK) Then
            ' lijst wordt automatisch bijgewerkt
            Dim toegevoegdArtikelRow As ArtikelsDataSet.ArtikelsRow = Utility.Data.Artikels.FindById(insertForm.ArtikelId)
            Dim laatstToegevoegdArtikelId As Integer = insertForm.ArtikelId
            aantal = insertForm.Aantal

            If (insertForm.ArtikelSoort = BeheerArtikelForm.ArtikelSoortType.Doos) Then
                Utility.ArtikelSamenstelling.AddHoofdArtikelId(insertForm.ArtikelId) ' lokale kopie van samengestelde artikels updaten
                ' vervang de doos door de artikelen die erin zitten
                Dim artikels As List(Of ArtikelSamenstelling.Artikel) = Utility.ArtikelSamenstelling.GetArtikels(toegevoegdArtikelRow)
                Debug.Assert(artikels.Count = 1, "Een toegevoegde doos kan nooit meerdere samenstellingen hebben")

                Dim deelArtikel As ArtikelSamenstelling.Artikel = artikels(0)
                Debug.Assert(deelArtikel.Aantal > 1, "Een doos moet meerdere artikels bevatten")

                aantal = aantal * deelArtikel.Aantal
                VoegArtikelMetBestaandeBarcodeToe(deelArtikel.ArtikelRij, aantal)
                laatstToegevoegdArtikelId = deelArtikel.ArtikelRij.Id

                toegevoegdArtikelRow.Voorraad = 0 ' verwijder de doos zelf uit de bindingsource (en uit de grid)
            End If

            ArtikelsDataSetBindingSource.Position = ArtikelsDataSetBindingSource.Find("ID", laatstToegevoegdArtikelId)
            lblVerwachteVoorraad.Text = "0"
            lblReedsGeteldAantal.Text = aantal.ToString()
            KanBewaren = True
            Return InvoerArtikelsControl.BarcodeStatusType.Valid
        Else
            ' barcode ook na mogelijkheid tot toevoegen niet gevonden
            lblVerwachteVoorraad.Text = "0"
            lblReedsGeteldAantal.Text = "0"
            Return InvoerArtikelsControl.BarcodeStatusType.Invalid
        End If
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="bestaandeRij"></param>
    ''' <param name="aantal"></param>
    ''' <returns></returns>
    Private Function VoegArtikelMetBestaandeBarcodeToe(ByVal bestaandeRij As ArtikelsDataSet.ArtikelsRow, ByVal aantal As Integer) _
                As InvoerArtikelsControl.BarcodeStatusType
        Dim idVanHuidigeBarcodeInDatabank As Integer = bestaandeRij.Id
        If (bestaandeRij.Voorraad <> 0) Then
            ' barcode staat al in de grid, selecteer de gegevens
            ArtikelsDataSetBindingSource.Position = ArtikelsDataSetBindingSource.Find("ID", idVanHuidigeBarcodeInDatabank)

            bestaandeRij.Voorraad += aantal
            Me.lblVerwachteVoorraad.Text = bestaandeRij.VerwachteVoorraad.ToString()
            Me.lblReedsGeteldAantal.Text = bestaandeRij.Voorraad.ToString()
            KanBewaren = True

            Sound.PlayWarning() ' verwittig de gebruiker dat de barcode al in de lijst staat
            ' toon de barcode in een speciale kleur om op te vallen
            Return InvoerArtikelsControl.BarcodeStatusType.Speciaal
        Else
            ' barcode staat nog niet in de grid
            ' tel het aantal bij de huidige voorraad
            bestaandeRij.Voorraad += aantal ' hierdoor voldoet de rij aan het filter en verschijnt ze vanzelf in de grid
            Me.lblVerwachteVoorraad.Text = bestaandeRij.VerwachteVoorraad.ToString()
            Me.lblReedsGeteldAantal.Text = bestaandeRij.Voorraad.ToString()
            ArtikelsDataSetBindingSource.Position = ArtikelsDataSetBindingSource.Find("ID", idVanHuidigeBarcodeInDatabank)
            KanBewaren = True

            Sound.PlayOK()
            Return InvoerArtikelsControl.BarcodeStatusType.Valid
        End If
    End Function

    Private Function BewaarWijzigingen() As Integer
        MyBase.Bewaar(Utility.Data.Artikels, "artikel(s)", KanBewaren)
    End Function

    Private Sub Verwijderen()
        Try
            Cursor = Cursors.WaitCursor
            'If (Me.ArtikelsDataSetBindingSource.Current IsNot Nothing) Then
            'Me.ArtikelsDataSetBindingSource.RemoveCurrent()
            'End If
            If Me.Grid1.SelectedRows.Count > 0 Then
                Dim selectedRow As DataGridViewRow = Grid1.SelectedRows(0)
                Dim artikelId As Integer = Convert.ToInt32(DataGridViewHelper.GetValueFromDataGridRow("ID", selectedRow))
                Dim dataRow As ArtikelsDataSet.ArtikelsRow = Utility.Data.Artikels.FindById(artikelId)

                ' hierdoor komt de voorraad weer op 0, en voldoet het niet meer aan het filter en verdwijnt het uit de grid
                ' dit werkt zowel voor toegevoegde artikels als voor gewijzigde artikels
                dataRow.RejectChanges()

                'Dim originalState As DataRowState = dataRow.RowState
                'Grid1.Rows.Remove(selectedRow)
                'If (Not originalState = DataRowState.Added) Then
                '' Dit artikel bestond al. Verwijder de rij in de grid, maar
                '' ook in de dataset (in plaats van een rij met RowState=Deleted te laten), 
                '' zodat er niets in de databank gewijzigd wordt
                ' Me.ArtikelsDataSet1.Artikels.RemoveArtikelsRow(dataRow)
                'End If

            End If
        Catch ex As Exception
            log.WriteError("Verwijderen", ex)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub BeheerArtikel(ByVal rowIndex As Integer)
        Try
            Cursor = Cursors.WaitCursor
            Dim gridRow As DataGridViewRow = Grid1.Rows(rowIndex)
            Dim datarow As DataRowView = DirectCast(gridRow.DataBoundItem, DataRowView)
            Dim artikelsRow As ArtikelsDataSet.ArtikelsRow = DirectCast(datarow.Row, ArtikelsDataSet.ArtikelsRow)
            Dim editForm As New BeheerArtikelForm(artikelsRow.Id, BeheerArtikelForm.Context.Inventaris)
            If (editForm.ShowDialog = DialogResult.OK) Then
                ' update grid gaat vanzelf
                'lblVerwachteVoorraad.Text = editForm.VerwachteVoorraadTextBox.Text ' kan niet gewijzigd worden
                lblReedsGeteldAantal.Text = editForm.Aantal.ToString()
                KanBewaren = True
                Me.InvoerArtikelsControl1.Clear()
            End If
        Catch ex As Exception
            log.WriteError("InventarisForm.BeheerArtikel", ex)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

#End Region

End Class